package com.cloudkinto.service.product.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.utils.ExcelUtils;
import com.cloudkinto.common.utils.StringsUtil;
import com.cloudkinto.common.utils.dict.StaticDict;
import com.cloudkinto.dao.*;
import com.cloudkinto.entity.*;
import com.cloudkinto.extentity.ProductStockDetailDto;
import com.cloudkinto.extentity.ProductStockRackDto;
import com.cloudkinto.extentity.StockFlowingDto;
import com.cloudkinto.extentity.StockFlowingShopDto;
import com.cloudkinto.extentity.stock.ProductStockDto;
import com.cloudkinto.service.product.ProductInfoService;
import com.cloudkinto.service.product.ProductOutService;
import com.cloudkinto.service.product.ProductStockFlowingService;
import com.cloudkinto.service.product.ProductStockRackService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cloudkinto.common.web.PageResult;
import com.cloudkinto.common.web.SingleResult;

import com.cloudkinto.service.product.importVo.DistributeStockImportRes;
import com.cloudkinto.service.product.importVo.DistributeStockImportVo;
import com.cloudkinto.service.product.vo.rack.*;
import com.cloudkinto.service.stock.StockLogService;
import com.cloudkinto.service.storage.StorageService;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * service实现类
 * </p>
 *
 * @author hua`
 * @since 2022-12-21
 */
@Service
@Transactional(rollbackFor = Exception.class)//事务回滚
public class ProductStockRackServiceImpl extends ServiceImpl<ProductStockRackDao, ProductStockRackDo> implements ProductStockRackService {
    @Autowired
    private ProductStockRackDao dao;
    @Autowired
    private StorageService storageService;
    @Autowired
    private StorageShelfDao storageShelfDao;
    @Autowired
    private StoragePositionDao storagePositionDao;
    @Autowired
    private StockRecordDao stockRecordDao;
    @Autowired
    private ProductStockDao productStockDao;
    @Autowired
    private ProductInfoDao productInfoDao;
    @Autowired
    private ProductStockFlowingService productStockFlowingService;
    @Autowired
    private ShopDao shopDao;
    @Autowired
    private StockLogService stockLogService;


    @Override
    public SingleResult addInit() {
        return SingleResult.success("");
    }

    @Override
    public Object add(Object req, Long userId) {
        ProductStockRackDo entityDo = new ProductStockRackDo();
        BeanUtils.copyProperties(req, entityDo);
        handlerAddBefore(entityDo, userId);
        dao.insert(entityDo);
        return handlerAddAfter(entityDo);
    }

    //新增校验
    private void addCheck(Object req) {

    }

    //做新增之前要执行的业务定制处理
    private void handlerAddBefore(ProductStockRackDo entityDo, Long userId) {
        entityDo.setCreateTime(new Date());
        entityDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
    }

    //将新增的do转换成要返回的实体
    private Object handlerAddAfter(ProductStockRackDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public SingleResult updateInit(Long id) {
        return SingleResult.success("");
    }

    @Override
    public Object update(Object req, Long userId) {
        /*ProductStockRackDo entityDo = dao.selectById(req.getId());
        BeanUtils.copyProperties(req, entityDo);
        handlerUpdateBefore(entityDo, userId);
        dao.updateById(entityDo);
        return handlerUpdateAfter(entityDo);*/
        return null;
    }

    //编辑校验
    private void updateCheck(Object req) {

    }

    //做修改之前要执行的业务定制处理
    private void handlerUpdateBefore(ProductStockRackDo entityDo, Long userId) {

    }

    //做修改之后要执行的业务定制处理
    private Object handlerUpdateAfter(ProductStockRackDo entityDo) {
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return res;
    }

    @Override
    public int delete(Long id, Long userId) {
        ProductStockRackDo entityDo = dao.selectById(id);
        handlerDeleteBefore(entityDo, userId);
        return dao.deleteById(id);
    }

    //做删除之前要执行的业务定制处理
    private void handlerDeleteBefore(ProductStockRackDo entityDo, Long userId) {

    }

    @Override
    public Object detail(Long id) {
        ProductStockRackDo entityDo = dao.selectById(id);
        Object res = new Object();
        BeanUtils.copyProperties(entityDo, res);
        return handlerDetailAfter(res);
    }

    //查询明细之后要执行的业务定制处理
    private Object handlerDetailAfter(Object res) {
        return res;
    }

    @Override
    public SingleResult pageInit() {
        Map<String, Object> result = new HashMap<>();
        result.put("storageList", storageService.getStorageList());
        return SingleResult.success(result);
    }

    @Override
    public List<ProductStockRackRes> getList(Map<String, String> map) {
        String keywordType = map.get("keyword");
        if (StringUtils.isNotBlank(keywordType)) {
            if ("默认库位".contains(keywordType)) {
                map.put("keywordType", "1");
            }
        }
        List<ProductStockRackDto> listPage = dao.getListPage(map);
        List<ProductStockRackRes> resList = handlerListAfter(listPage);
        return resList;
    }

    @Override
    public PageResult getListPage(Map<String, String> map) {
//        QueryWrapper<ProductStockRackDo> wrapper = queryBuild(map);
        String keywordType = map.get("keyword");
        if (StringUtils.isNotBlank(keywordType)) {
            if ("默认库位".contains(keywordType)) {
                map.put("keywordType", "1");
            }
        }
        IPage<ProductStockRackDto> page = pageInitDto(map);
        page = dao.getListPage(page, map);
        List<ProductStockRackRes> resList = handlerListAfter(page.getRecords());
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    //查询分页列表之后对列表数据的处理
    private List<ProductStockRackRes> handlerListAfter(List<ProductStockRackDto> list) {
        List<ProductStockRackRes> result = new ArrayList<>();
        for (ProductStockRackDto productStockRackDto : list) {
            ProductStockRackRes res = new ProductStockRackRes();
            BeanUtils.copyProperties(productStockRackDto, res);
            result.add(res);
        }
        return result;
    }

    private IPage<ProductStockRackDo> pageInit(Map<String, String> map) {
        IPage<ProductStockRackDo> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private IPage<StockFlowingDto> pageInitFlowingDto(Map<String, String> map) {
        IPage<StockFlowingDto> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private IPage<ProductStockRackDto> pageInitDto(Map<String, String> map) {
        IPage<ProductStockRackDto> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private IPage<ProductStockDetailDto> pageInitDDto(Map<String, String> map) {
        IPage<ProductStockDetailDto> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }

    private QueryWrapper<ProductStockRackDo> queryBuild(Map<String, String> map) {
        QueryWrapper<ProductStockRackDo> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(map.get("keyword"))) {
            wrapper.like("keyword", map.get("keyword"));
        }
        return wrapper;
    }


    @Override
    public PageResult getStockByRackId(Map<String, String> map) {
        map.put("notStore", "1");
        IPage<ProductStockDetailDto> page = pageInitDDto(map);
        page = dao.getStockByRackId(page, map);
        List<ProductStockDetailRes> resList = new ArrayList<>();
        for (ProductStockDetailDto record : page.getRecords()) {
            ProductStockDetailRes res = new ProductStockDetailRes();
            BeanUtils.copyProperties(record, res);
            //获取盘盈盘亏 数量

            LambdaQueryWrapper<ProductStockFlowingDo> q = new LambdaQueryWrapper<>();
            if (res.getRackId() == null) {
                q.isNull(ProductStockFlowingDo::getRackId);
            } else {
                q.eq(ProductStockFlowingDo::getRackId, res.getRackId());
            }
            q.eq(ProductStockFlowingDo::getProductId, res.getProductId());
            q.eq(ProductStockFlowingDo::getStorageId, res.getStorageId());
            q.ne(ProductStockFlowingDo::getStatus, "done");

            int good = productStockFlowingService.list(q).stream().mapToInt(ProductStockFlowingDo::getGoodQuantity).sum();
            int bad = productStockFlowingService.list(q).stream().mapToInt(ProductStockFlowingDo::getBadQuantity).sum();
            res.setUnCheckGood(good);
            res.setUnCheckBad(bad);
            resList.add(res);
        }
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }


    @Override
    public PageResult getStockList(Map<String, String> map) {
        IPage<ProductStockDetailDto> page = pageInitDDto(map);
        page = dao.getStockList(page, map);
        List<ProductStockDetailRes> resList = new ArrayList<>();
        for (ProductStockDetailDto record : page.getRecords()) {
            ProductStockDetailRes res = new ProductStockDetailRes();
            BeanUtils.copyProperties(record, res);
            resList.add(res);
        }
        PageResult result = new PageResult(resList, (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }

    @Override
    public List<ProductStockDetailRes> getStockListAll(Map<String, String> map) {
        List<ProductStockDetailDto> list = dao.getStockList(map);
        List<ProductStockDetailRes> resList = new ArrayList<>();
        for (ProductStockDetailDto record : list) {
            ProductStockDetailRes res = new ProductStockDetailRes();
            BeanUtils.copyProperties(record, res);
            resList.add(res);
        }

        return resList;
    }

    @Override
    public SingleResult updateStockInit(Map<String, String> map) {
        map.put("notStore", "1");
        SingleResult singleResult = new SingleResult();
        ProductStockDetailDto detailDto = dao.getStockByRackId(map);
        Map mapInfo = new HashMap();
        mapInfo.put("rackList", this.getPostions(map.get("storageId")));
        singleResult.setMapInfo(mapInfo);

        singleResult.setData(detailDto);

        return singleResult;
    }

    @Override
    public List<StoragePositionDo> getPostions(String storageId) {
        List<StorageShelfDo> storageShelfDos = storageShelfDao.selectList(new LambdaQueryWrapper<StorageShelfDo>().eq(StorageShelfDo::getStorageId, storageId));
        if (storageShelfDos.size() > 0) {
            List<StoragePositionDo> positionDos = storagePositionDao.selectList(new LambdaQueryWrapper<StoragePositionDo>().in(StoragePositionDo::getShelfId, storageShelfDos.stream().map(StorageShelfDo::getId).collect(Collectors.toList())));
            return positionDos;
        }
        return new ArrayList<>();
    }


    /**
     * 批量分配库存
     *
     * @param userId
     * @param companyId
     */
    @Override
    public void distributeStockBatch(List<DistributeStockReq> reqs, Long userId, Long companyId) {
        if (reqs.size() > 0) for (DistributeStockReq req : reqs) {
            Map<String, Object> result = this.distributeStockMap(req, userId, companyId, false);
            if ("500".equals(result.get("code").toString())) {
                throw new BizException(result.get("msg").toString());
            }
        }

    }

    /**
     * 分配库存
     *
     * @param req
     * @param userId
     * @param companyId
     */
    @Override
    public void distributeStock(DistributeStockReq req, Long userId, Long companyId) {
        Map<String, Object> result = this.distributeStockMap(req, userId, companyId, false);
        if ("500".equals(result.get("code").toString())) {
            throw new BizException(result.get("msg").toString());
        }
    }


    @Override
    public SingleResult importDistributeStock(MultipartFile file, Long fromStorageId, Long fromRackId, Long userId, Long companyId) {
        String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!GlobalConstants.IMG_TYPE_XLS.equals(suffix.toUpperCase()) && !GlobalConstants.IMG_TYPE_XLSX.equals(suffix.toUpperCase())) {
            throw new BizException(SysConstant.File_Form_Incorrect);
        }

        List<DistributeStockImportVo> excelImportList = new ArrayList<>();
        try {
            excelImportList = ExcelUtils.importExcel(file, 1, 0, DistributeStockImportVo.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (excelImportList.size() == 0) {
            throw new BizException(SysConstant.File_FormWork_Incorrect);
        }

        List<DistributeStockImportRes> resList = new ArrayList<>();
        for (int i = 0; i < excelImportList.size(); i++) {
            DistributeStockImportVo importVo = excelImportList.get(i);
            StoragePositionDo positionDo = storagePositionDao.getRackByRackName(fromStorageId, importVo.getShelfName(), importVo.getPositionName());
            if (positionDo == null) {
                resList.add(new DistributeStockImportRes(i + 1, "货架:" + importVo.getShelfName() + "不存在或者 货架 " + importVo.getShelfName() + "下 库位" + importVo.getPositionName() + "不存在"));
                continue;
            }
            if (positionDo.getId().equals(fromRackId)) {
                resList.add(new DistributeStockImportRes(i + 1, "源库位 等于 目的库位"));
                continue;
            }
            //去查 源库位库存
            ProductInfoDo productInfoDo = productInfoDao.selectOne(new LambdaQueryWrapper<ProductInfoDo>().eq(ProductInfoDo::getCommoditySku, importVo.getCommoditySku())
                    .or().eq(ProductInfoDo::getStorageSku, importVo.getCommoditySku()));
            if (productInfoDo == null) {
                resList.add(new DistributeStockImportRes(i + 1, "sku:" + importVo.getCommoditySku() + "不存在"));
                continue;
            }
            DistributeStockReq req = new DistributeStockReq();
            req.setProductId(productInfoDo.getId());
            req.setStorageId(fromStorageId);
            req.setFromRackId(fromRackId);
            req.setToRackId(positionDo.getId());
            req.setGoodQuantity(importVo.getGoodQuantity());
            req.setBadQuantity(importVo.getBadQuantity());
            req.setTips("excel导入");

            Map<String, Object> result = this.distributeStockMap(req, userId, companyId, true);
            if ("500".equals(result.get("code").toString())) {
                resList.add(new DistributeStockImportRes(i + 1, result.get("msg").toString()));
                continue;
            }
        }
        return SingleResult.success("导入成功", resList);
    }


    public Map<String, Object> distributeStockMap(DistributeStockReq req, Long userId, Long companyId, boolean isImport) {
        Map<String, Object> result = new HashMap<>();
        if (req.getGoodQuantity() <= 0 && req.getBadQuantity() <= 0) {
            result.put("code", 500);
            result.put("msg", StringsUtil.createI18Message("良品或次品必须大于0"));
            return result;
        }
        if (req.getFromRackId() == null && req.getToRackId() == null) {
            result.put("code", 500);
            result.put("msg", StringsUtil.createI18Message("出库库位不能等于 目的库位"));
            return result;
        } else if (req.getFromRackId() != null && req.getToRackId() != null && req.getFromRackId().equals(req.getToRackId())) {
            result.put("code", 500);
            result.put("msg", StringsUtil.createI18Message("出库库位不能等于 目的库位"));
            return result;
        }
        Map<String, String> map = new HashMap<>();
        map.put("productId", req.getProductId() + "");
        if (req.getFromRackId() != null) {
            map.put("rackId", req.getFromRackId() + "");
        }
        map.put("storageId", req.getStorageId() + "");
        if (companyId != null) {
            map.put("companyId", companyId + "");
        }
        map.put("store", "0");
        ProductStockDetailDto detailDto = dao.getStockByRackId(map);

        ProductInfoDo productInfoDo = productInfoDao.selectById(req.getProductId());
        if (isImport) {
            if (detailDto == null) {
                UpdateStockReq updateStockReq = new UpdateStockReq();
                updateStockReq.setProductId(req.getProductId());
                updateStockReq.setGoodQuantity(req.getGoodQuantity());
                updateStockReq.setBadQuantity(req.getBadQuantity());
                updateStockReq.setRackId(null);
                updateStockReq.setStorageId(req.getStorageId());
                updateStockReq.setStore(0);
                updateStock(updateStockReq, userId, companyId);
            } else if (
                    detailDto.getGoodQuantity() < req.getGoodQuantity()
                            || detailDto.getBadQuantity() < req.getBadQuantity()) {
                UpdateStockReq updateStockReq = new UpdateStockReq();
                updateStockReq.setProductId(req.getProductId());
                updateStockReq.setRackId(detailDto.getRackId());
                updateStockReq.setStorageId(req.getStorageId());
                updateStockReq.setStore(0);
                updateStockReq.setGoodQuantity(req.getGoodQuantity());
                updateStockReq.setBadQuantity(req.getBadQuantity() > detailDto.getBadQuantity() ? req.getBadQuantity() : detailDto.getBadQuantity());
                updateStock(updateStockReq, userId, companyId);
//            result.put("code", 500);
//            result.put("msg", "sku:" + detailDto.getCommoditySku() + "可售库存不够");
//            return result;
            }
        } else {
            if (detailDto == null) {
                result.put("code", 500);
                result.put("msg", String.format(StringsUtil.createI18Message(SysConstant.StockRack_NotEnough_Sku), productInfoDo != null ? productInfoDo.getCommoditySku() : ""));
                return result;
            }
            if (detailDto.getGoodQuantity() < req.getGoodQuantity()) {
                result.put("code", 500);
                result.put("msg", "sku:" + detailDto.getCommoditySku() + "可售库存不够");
                return result;
            }
            if (detailDto.getBadQuantity() < req.getBadQuantity()) {
                result.put("code", 500);
                result.put("msg", "sku:" + detailDto.getCommoditySku() + "破损数量不够");
                return result;
            }
        }

        int goodQuantity = req.getGoodQuantity();
        int badQuantity = req.getBadQuantity();

        List<ProductStockRackDo> rackDoList = dao.getStockRackList(map);

        for (ProductStockRackDo rackDo : rackDoList) {
            ProductStockDo stockDo = productStockDao.selectById(rackDo.getStockId());
            if (stockDo == null) {
                result.put("code", 500);
                result.put("msg", "库存 stock 不存在");
                return result;
            }
        }
        String fromRackName = "默认库位";
        String toRackName = "默认库位";
        if (req.getFromRackId() != null) {
            StoragePositionDo from = storagePositionDao.selectById(req.getFromRackId());
            fromRackName = from.getPositionName();
        }
        if (req.getToRackId() != null) {
            StoragePositionDo from = storagePositionDao.selectById(req.getToRackId());
            toRackName = from.getPositionName();
        }
        for (ProductStockRackDo rackDo : rackDoList) {
            //减库存
            Map<String, Integer> resultMap = this.dealWithOneRackStock(goodQuantity, badQuantity, rackDo, StaticDict.Product_Flowing_Type.DistributeStock.getValue(), null, fromRackName + "调出至" + toRackName, userId);
            int dGood = resultMap.get("dGood");
            int dBad = resultMap.get("dBad");
            goodQuantity = resultMap.get("goodQuantity");
            badQuantity = resultMap.get("badQuantity");


            //减完库存再去新增
            ProductStockRackDo newRackDo = new ProductStockRackDo();
            newRackDo.setStockId(rackDo.getStockId());
            newRackDo.setRackId(req.getToRackId());
            newRackDo.setGoodQuantity(dGood);
            newRackDo.setBadQuantity(dBad);
            newRackDo.setCreateTime(new Date());
            dao.insert(newRackDo);

            ProductStockDo stockDo = productStockDao.selectById(rackDo.getStockId());

            if (dGood != 0 || dBad != 0) {
                //库存流水新
                productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.DistributeStock.getValue(), req.getProductId(), req.getStorageId(), dGood, dBad, req.getToRackId(), stockDo.getCompanyId(), userId, fromRackName + "调入至" + toRackName);
            }

            if (goodQuantity <= 0 && badQuantity <= 0) {
                break;
            }
        }
        if (goodQuantity > 0) {
            result.put("code", 500);
            result.put("msg", "sku:" + productInfoDo.getCommoditySku() + "可售库存不够");
            return result;
        }
        if (badQuantity > 0) {
            result.put("code", 500);
            result.put("msg", "sku:+" + productInfoDo.getCommoditySku() + "破损数量不够");
            return result;
        }
        result.put("code", 200);
        return result;
    }

    /**
     * 配货区配货
     */
    @Override
    public void distributeStore(DistributeStoreReq req, Long companyId, Long userId) {
        if (req.getGoodQuantity() <= 0 && req.getBadQuantity() <= 0) {
            throw new BizException("良品或次品必须大于0");
        }
        if (req.getStore() == 0) {
            //发货区调入配过去，目标库位只能是默认库位
            req.setToRackId(null);
        }
        Map<String, String> map = new HashMap<>();
        map.put("productId", req.getProductId() + "");
        if (req.getFromRackId() != null) {
            map.put("rackId", req.getFromRackId() + "");
        }
        map.put("storageId", req.getStorageId() + "");
        if (companyId != null) {
            map.put("companyId", companyId + "");
        }
        map.put("store", req.getStore() + "");
        ProductStockDetailDto detailDto = dao.getStockByRackId(map);
        ProductInfoDo productInfoDo = productInfoDao.selectById(req.getProductId());
        if (detailDto == null) {
            throw new BizException(String.format(StringsUtil.createI18Message(SysConstant.StockRack_NotEnough_Sku), productInfoDo != null ? productInfoDo.getCommoditySku() : ""));
        }
        if (detailDto.getGoodQuantity() < req.getGoodQuantity()) {
            throw new BizException(SysConstant.StockRack_Good_NotEnough_Sku, productInfoDo.getCommoditySku());
        }
        if (detailDto.getBadQuantity() < req.getBadQuantity()) {
            throw new BizException(SysConstant.StockRack_Bad_NotEnough_Sku, productInfoDo.getCommoditySku());
        }
        int goodQuantity = req.getGoodQuantity();
        int badQuantity = req.getBadQuantity();

        List<ProductStockRackDo> rackDoList = dao.getStockRackList(map);

        for (ProductStockRackDo rackDo : rackDoList) {
            ProductStockDo stockDo = productStockDao.selectById(rackDo.getStockId());
            if (stockDo == null) {
                throw new BizException("库存 stock 不存在");
            }
        }

        for (ProductStockRackDo rackDo : rackDoList) {
            //减库存
            Map<String, Integer> resultMap = this.dealWithOneRackStock(goodQuantity, badQuantity, rackDo, StaticDict.Product_Flowing_Type.DistributeStore.getValue(), null, req.getStore() == 0 ? "发货区调出至配货区" : "配货区调出至发货区", userId);
            int dGood = resultMap.get("dGood");
            int dBad = resultMap.get("dBad");
            goodQuantity = resultMap.get("goodQuantity");
            badQuantity = resultMap.get("badQuantity");


            //减完配货区 库存再去新增发货区库存
            ProductStockRackDo newRackDo = new ProductStockRackDo();
            newRackDo.setStockId(rackDo.getStockId());
            newRackDo.setRackId(req.getToRackId());
            newRackDo.setStore(req.getStore() == 0 ? 1 : 0);
            newRackDo.setGoodQuantity(dGood);
            newRackDo.setBadQuantity(dBad);
            newRackDo.setCreateTime(new Date());
            dao.insert(newRackDo);

            ProductStockDo stockDo = productStockDao.selectById(rackDo.getStockId());

            if (dGood != 0 || dBad != 0) {
                //库存流水新
                productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.DistributeStore.getValue(), req.getProductId(), req.getStorageId(), dGood, dBad, req.getToRackId(), stockDo.getCompanyId(), userId, req.getStore() == 0 ? "发货区调入至配货区" : "配货区调入至发货区");
            }

            if (goodQuantity <= 0 && badQuantity <= 0) {
                break;
            }
        }
        if (goodQuantity > 0) {
            throw new BizException(SysConstant.StockRack_Good_NotEnough_Sku, productInfoDo.getCommoditySku());
        }
        if (badQuantity > 0) {
            throw new BizException(SysConstant.StockRack_Bad_NotEnough_Sku, productInfoDo.getCommoditySku());
        }
    }


    @Override
    public void updateStockBatch(List<UpdateStockReq> reqs, Long userId, Long companyId) {
        for (UpdateStockReq req : reqs) {
            updateStock(req, userId, companyId);
        }
    }

    @Override
    public void updateStock(UpdateStockReq req, Long userId, Long companyId) {
        Map<String, String> map = new HashMap<>();
        if (req.getProductId() == null) {
            LambdaQueryWrapper<ProductInfoDo> productInfoDoLambdaQueryWrapper = new LambdaQueryWrapper<>();
            productInfoDoLambdaQueryWrapper.eq(ProductInfoDo::getCommoditySku, req.getSku())
                    .or().eq(ProductInfoDo::getStorageSku, req.getSku());
            List<ProductInfoDo> productInfoDoList = productInfoDao.selectList(productInfoDoLambdaQueryWrapper);
            if (productInfoDoList.size() < 1) {
                throw new BizException(SysConstant.Product_NotExist_Sku, req.getSku());
            }
            if (productInfoDoList.size() > 1) {
                throw new BizException(SysConstant.StockRack_Update_Error, req.getSku());
            }
            req.setProductId(productInfoDoList.get(0).getId());
        }
        map.put("productId", req.getProductId() + "");
        if (req.getRackId() != null) {
            map.put("rackId", req.getRackId() + "");
        }
        map.put("storageId", req.getStorageId() + "");
        if (companyId != null) {
            map.put("companyId", companyId + "");
        }
        map.put("store", req.getStore() + "");//发货区还是配货区
        if (req.getGoodQuantity() > 0 || req.getBadQuantity() > 0) {
            this.updateStockAdd(req, null, userId, companyId, true, req.getTips());
        }

        if (req.getGoodQuantity() < 0 || req.getBadQuantity() < 0) {
            this.updateStockReduce(req, map, null, userId, companyId, true, req.getTips());
        }
    }


    public Long updateStockReduce(UpdateStockReq req, Map<String, String> map, Long flowingId, Long userId, Long companyId, boolean flowingFlag, String tips) {
        if (req.getGoodQuantity() < 0 || req.getBadQuantity() < 0) {
            ProductStockDetailDto detailDto = dao.getStockByRackId(map);
            if (detailDto == null) {
                throw new BizException(SysConstant.StockRack_Good_NotEnough);
            }
            if (req.getGoodQuantity() < 0 && (detailDto.getGoodQuantity() + req.getGoodQuantity()) < 0) {
                throw new BizException(SysConstant.StockRack_Good_NotEnough);
            }
            if (req.getBadQuantity() < 0 && (detailDto.getBadQuantity() + req.getBadQuantity()) < 0) {
                throw new BizException(SysConstant.StockRack_Bad_NotEnough);
            }
        }

        ProductInfoDo productInfoDo = productInfoDao.selectById(req.getProductId());
        Long oneShopId = null;
        Map<Long, String> shopCount = new HashMap<>();
        if (req.getList() != null && req.getList().size() > 0) {
            if (req.getGoodQuantity() < 0 && req.getList().stream().mapToInt(ShopStockReq::getGood).sum() != req.getGoodQuantity()) {
                throw new BizException(SysConstant.No_Data);
            }
            if (req.getBadQuantity() < 0 && req.getList().stream().mapToInt(ShopStockReq::getBad).sum() != req.getBadQuantity()) {
                throw new BizException(SysConstant.No_Data);
            }
            for (ShopStockReq shopStockReq : req.getList()) {
                //更新旧表库存
                LambdaQueryWrapper<StockRecordDo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(StockRecordDo::getShopId, shopStockReq.getId());
//                queryWrapper.and(i -> i.gt(StockRecordDo::getCanSellCount, 0).or().gt(StockRecordDo::getCanotSellCount, 0));
                queryWrapper.eq(StockRecordDo::getProductInfoId, req.getProductId());
                queryWrapper.eq(StockRecordDo::getStorageId, req.getStorageId());
                queryWrapper.orderByDesc(StockRecordDo::getCanSellCount);
                StockRecordDo recordDo = stockRecordDao.selectOne(queryWrapper);
                if (recordDo == null) {
                    throw new BizException(SysConstant.Stock_Old_NotExist);
                }

                int goodQuantity1 = shopStockReq.getGood() < 0 ? -shopStockReq.getGood() : 0;
                int badQuantity1 = shopStockReq.getBad() < 0 ? -shopStockReq.getBad() : 0;

                if (goodQuantity1 > recordDo.getCanSellCount()) {
                    throw new BizException(SysConstant.StockRecord_ShopGood_Error, shopStockReq.getShopName());
                }
                if (badQuantity1 > recordDo.getCanotSellCount()) {
                    throw new BizException(SysConstant.StockRecord_ShopBad_Error, shopStockReq.getShopName());
                }
                recordDo.setCanSellCount(recordDo.getCanSellCount() - goodQuantity1);
                recordDo.setCanotSellCount(recordDo.getCanotSellCount() - badQuantity1);
                stockRecordDao.updateById(recordDo);

                if (goodQuantity1 > 0 || badQuantity1 > 0) {
                    oneShopId = shopStockReq.getId();
                    shopCount.put(recordDo.getShopId(), goodQuantity1 + "@" + badQuantity1 + "@" + recordDo.getCanSellCount() + "@" + recordDo.getCanotSellCount());
                }
            }
        }
        else {
            //不指定店铺 就随机扣店铺库存
            //更新旧表库存
            LambdaQueryWrapper<StockRecordDo> queryWrapper = new LambdaQueryWrapper<>();
            if (companyId != null) {
                queryWrapper.eq(StockRecordDo::getCompanyId, companyId);
            }
            queryWrapper.and(i -> i.gt(StockRecordDo::getCanSellCount, 0).or().gt(StockRecordDo::getCanotSellCount, 0));
            queryWrapper.eq(StockRecordDo::getProductInfoId, req.getProductId());
            queryWrapper.eq(StockRecordDo::getStorageId, req.getStorageId());
            queryWrapper.orderByDesc(StockRecordDo::getCanSellCount);

            List<StockRecordDo> recordDoList = stockRecordDao.selectList(queryWrapper);
            int goodQuantity1 = req.getGoodQuantity() < 0 ? -req.getGoodQuantity() : 0;
            int badQuantity1 = req.getBadQuantity() < 0 ? -req.getBadQuantity() : 0;

            for (StockRecordDo recordDo : recordDoList) {
                oneShopId = recordDo.getShopId();
                int dGood = 0;
                int dBad = 0;
                if (recordDo.getCanSellCount() >= goodQuantity1) {
                    dGood = goodQuantity1;
                    goodQuantity1 = 0;
                } else {
                    dGood = recordDo.getCanSellCount();
                    goodQuantity1 = goodQuantity1 - recordDo.getCanSellCount();
                }

                if (recordDo.getCanotSellCount() >= badQuantity1) {
                    dBad = badQuantity1;
                    badQuantity1 = 0;
                } else {
                    dBad = recordDo.getCanotSellCount();
                    badQuantity1 = badQuantity1 - recordDo.getCanotSellCount();
                }
                if (dGood == 0 && dBad == 0) {
                    continue;
                }
                //如果减少要添加出库记录
                recordDo.setCanSellCount(recordDo.getCanSellCount() - dGood);
                recordDo.setCanotSellCount(recordDo.getCanotSellCount() - dBad);
                stockRecordDao.updateById(recordDo);

                if (dGood > 0 || dBad > 0) {
                    shopCount.put(recordDo.getShopId(), dGood + "@" + dBad + "@" + recordDo.getCanSellCount() + "@" + recordDo.getCanotSellCount());
                }
                if (goodQuantity1 <= 0 && badQuantity1 <= 0) {
                    break;
                }

            }
            if (goodQuantity1 > 0) {
                throw new BizException(SysConstant.StockRack_Good_NotEnough_old);
            }
            if (badQuantity1 > 0) {
                throw new BizException(SysConstant.StockRack_Bad_NotEnough_old);
            }
        }
        List<ProductStockRackDo> rackDoList = dao.getStockRackList(map);
        //按店铺 扣新表 库存
        for (Long shopId : shopCount.keySet()) {
            int goodQuantity = Integer.parseInt(shopCount.get(shopId).split("@")[0]);
            int badQuantity = Integer.parseInt(shopCount.get(shopId).split("@")[1]);
            for (ProductStockRackDo rackDo : rackDoList) {
                //单纯减库存，也要更新旧表库存
                Map<String, Integer> resultMap = this.dealWithOneRackStock(goodQuantity, badQuantity, rackDo, StaticDict.Product_Flowing_Type.RackUpdate.getValue(), shopId, this.getTips(req.getStore()), userId, false);
                int dGood = resultMap.get("dGood");
                int dBad = resultMap.get("dBad");
                if (dGood == 0 && dBad == 0) {
                    continue;
                }
                goodQuantity = resultMap.get("goodQuantity");
                badQuantity = resultMap.get("badQuantity");
                productStockDao.updateStockById2(rackDo.getStockId(), dGood, dBad);

                if (goodQuantity <= 0 && badQuantity <= 0) {
                    break;
                }
            }
            if (goodQuantity > 0) {
                throw new BizException(SysConstant.StockRack_Good_NotEnough_New);
            }
            if (badQuantity > 0) {
                throw new BizException(SysConstant.StockRack_Bad_NotEnough_New);
            }
            if (flowingFlag) {
                flowingId = productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.RackUpdate.getValue(), shopId, req.getProductId(), req.getStorageId(),
                        -Integer.parseInt(shopCount.get(shopId).split("@")[0]), -Integer.parseInt(shopCount.get(shopId).split("@")[1]), req.getRackId(), productInfoDo.getCompanyId(), userId, StringUtils.isNotBlank(tips) ? tips : this.getTips(req.getStore()));
            }
            this.insertOldStockLog(tips, -Integer.parseInt(shopCount.get(shopId).split("@")[0]), -Integer.parseInt(shopCount.get(shopId).split("@")[1]), req.getProductId(), req.getStorageId(), shopId, Integer.parseInt(shopCount.get(shopId).split("@")[2]),
                    Integer.parseInt(shopCount.get(shopId).split("@")[3]), userId, req.getStore(), flowingId);
        }
        if (shopCount.keySet().size() == 1) {
            return oneShopId;
        } else {
            return null;
        }
    }


    public Long updateStockAdd(UpdateStockReq req, Long flowingId, Long userId, Long companyId, boolean flowingFlag, String tips) {
        ProductInfoDo productInfoDo = productInfoDao.selectById(req.getProductId());
        if (productInfoDo == null) {
            throw new BizException(SysConstant.Product_NotExist);
        }
        Long oneShopId = null;
        Map<Long, String> shopCount = new HashMap<>();
        if (req.getList() != null && req.getList().size() > 0) {
            for (ShopStockReq shopStockReq : req.getList()) {
                //更新旧表库存
                LambdaQueryWrapper<StockRecordDo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(StockRecordDo::getShopId, shopStockReq.getId());
                queryWrapper.eq(StockRecordDo::getProductInfoId, req.getProductId());
                queryWrapper.eq(StockRecordDo::getStorageId, req.getStorageId());
                queryWrapper.orderByDesc(StockRecordDo::getCanSellCount);
                StockRecordDo recordDo = stockRecordDao.selectOne(queryWrapper);

                if (recordDo == null) {
                    recordDo = new StockRecordDo();
                    recordDo.setStorageId(req.getStorageId());
                    recordDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                    recordDo.setCompanyId(productInfoDo.getCompanyId());
                    recordDo.setProductInfoId(req.getProductId());
                    recordDo.setShopId(shopStockReq.getId());
                }
                recordDo.setUpdateBy(userId);
                recordDo.setUpdateTime(new Date());

                int goodQuantity1 = shopStockReq.getGood() > 0 ? shopStockReq.getGood() : 0;
                int badQuantity1 = Math.max(shopStockReq.getBad(), 0);

                recordDo.setCanSellCount(recordDo.getCanSellCount() + goodQuantity1);
                recordDo.setCanotSellCount(recordDo.getCanotSellCount() + badQuantity1);

                if (recordDo.getId() == null) {
                    stockRecordDao.insert(recordDo);
                } else {
                    stockRecordDao.updateById(recordDo);
                }

                if (goodQuantity1 > 0 || badQuantity1 > 0) {
                    oneShopId = shopStockReq.getId();
                    shopCount.put(recordDo.getShopId(), goodQuantity1 + "@" + badQuantity1 + "@" + recordDo.getCanSellCount() + "@" + recordDo.getCanotSellCount());
                }
            }
        }
        else {
            //不指定店铺 就随机添加到 店铺库存
            //去查哪家的库存最少
            LambdaQueryWrapper<StockRecordDo> queryWrapper = new LambdaQueryWrapper<>();
            if (companyId != null) {
                queryWrapper.eq(StockRecordDo::getCompanyId, companyId);
            }
            queryWrapper.eq(StockRecordDo::getProductInfoId, req.getProductId());
            queryWrapper.eq(StockRecordDo::getStorageId, req.getStorageId());
            queryWrapper.orderByAsc(StockRecordDo::getCanSellCount);
            queryWrapper.last(" limit 1");

            StockRecordDo recordDo = stockRecordDao.selectOne(queryWrapper);
            if (recordDo == null) {
                recordDo = new StockRecordDo();
                recordDo.setStorageId(req.getStorageId());
                recordDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
                recordDo.setCompanyId(productInfoDo.getCompanyId());
                recordDo.setProductInfoId(req.getProductId());
                ShopDo shopDo = shopDao.selectOne(new LambdaQueryWrapper<ShopDo>().eq(ShopDo::getCompanyId, productInfoDo.getCompanyId()).last(" limit 1"));
                if (shopDo == null) {
                    throw new BizException(SysConstant.StockRack_NoShop);
                }
                recordDo.setShopId(shopDo.getId());
            }
            recordDo.setUpdateBy(userId);
            recordDo.setUpdateTime(new Date());

            int goodQuantity1 = req.getGoodQuantity() > 0 ? req.getGoodQuantity() : 0;
            int badQuantity1 = Math.max(req.getBadQuantity(), 0);
            recordDo.setCanSellCount(recordDo.getCanSellCount() + goodQuantity1);
            recordDo.setCanotSellCount(recordDo.getCanotSellCount() + badQuantity1);

            if (recordDo.getId() == null) {
                stockRecordDao.insert(recordDo);
            } else {
                stockRecordDao.updateById(recordDo);
            }
            if (goodQuantity1 > 0 || badQuantity1 > 0) {
                shopCount.put(recordDo.getShopId(), goodQuantity1 + "@" + badQuantity1 + "@" + recordDo.getCanSellCount() + "@" + recordDo.getCanotSellCount());
            }
            oneShopId = recordDo.getShopId();
        }
        ProductStockDo stockDo = new ProductStockDo();
        stockDo.setProductId(req.getProductId());
        stockDo.setCompanyId(productInfoDo.getCompanyId());
        stockDo.setStorageId(req.getStorageId());
        stockDo.setOrderType("rackUpdate");
        stockDo.setCreateTime(new Date());
        stockDo.setCreateBy(userId);
//            stockDo.setShopId(recordDo.getShopId());

        int receiveQuantity = 0;
        int flowingGood = 0;
        int flowingBad = 0;
        if (req.getGoodQuantity() > 0) {
            receiveQuantity += req.getGoodQuantity();
            stockDo.setReceiveGoodQuantity(req.getGoodQuantity());
            stockDo.setGoodQuantity(req.getGoodQuantity());
            flowingGood = req.getGoodQuantity();
        }
        if (req.getBadQuantity() > 0) {
            receiveQuantity += req.getBadQuantity();
            stockDo.setBadQuantity(req.getBadQuantity());
            flowingBad = req.getBadQuantity();
        }
        stockDo.setReceiveQuantity(receiveQuantity);
        productStockDao.insert(stockDo);

//        //插入旧表库存
//        insertOldStockLog(req.getGoodQuantity(), req.getBadQuantity(), req.getProductId(), req.getStorageId(), userId, recordDo, req.getStore(), null);
        //插入库位表
        ProductStockRackDo rackDo = new ProductStockRackDo();
        rackDo.setRackId(req.getRackId());
        rackDo.setCreateTime(new Date());
        rackDo.setStockId(stockDo.getId());
        rackDo.setStore(req.getStore());
        if (req.getGoodQuantity() > 0) {
            rackDo.setGoodQuantity(req.getGoodQuantity());
        }
        if (req.getBadQuantity() > 0) {
            rackDo.setBadQuantity(req.getBadQuantity());
        }
        dao.insert(rackDo);

//        if (flowingFlag) {
//            //库存流水新
//            productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.RackUpdate.getValue(), recordDo.getShopId(), req.getProductId(), req.getStorageId(), flowingGood, flowingBad, req.getRackId(), stockDo.getCompanyId(), userId, this.getTips(req.getStore()));
//        }

        //按店铺 添加新表 库存
        for (Long shopId : shopCount.keySet()) {
            if (flowingFlag) {
                flowingId = productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.RackUpdate.getValue(), shopId, req.getProductId(), req.getStorageId(),
                        Integer.parseInt(shopCount.get(shopId).split("@")[0]), Integer.parseInt(shopCount.get(shopId).split("@")[1]), req.getRackId(), productInfoDo.getCompanyId(), userId, StringUtils.isNotBlank(tips) ? tips : this.getTips(req.getStore()));
            }
           this.insertOldStockLog(tips, Integer.parseInt(shopCount.get(shopId).split("@")[0]), Integer.parseInt(shopCount.get(shopId).split("@")[1]), req.getProductId(), req.getStorageId(), shopId, Integer.parseInt(shopCount.get(shopId).split("@")[2]),
                    Integer.parseInt(shopCount.get(shopId).split("@")[3]), userId, req.getStore(), flowingId);
        }

        if (shopCount.keySet().size() == 1) {
            return oneShopId;
        } else {
            return null;
        }
    }

    @Override
    public void doneApply(DoneUpdateStockReq req, Long userId) {
        ProductStockFlowingDo flowingDo = productStockFlowingService.getById(req.getId());
        if (flowingDo == null) {
            throw new BizException(SysConstant.No_Data);
        }
        if (!"checked".equals(flowingDo.getStatus())) {
            throw new BizException(SysConstant.Status_Error);
        }
        flowingDo.setGoodQuantity(req.getGoodQuantity());
        flowingDo.setBadQuantity(req.getBadQuantity());
        flowingDo.setFinishBy(userId);
        flowingDo.setFinishTime(new Date());
        flowingDo.setStatus("done");
        Map<String, String> map = new HashMap<>();
        map.put("productId", flowingDo.getProductId() + "");
        if (flowingDo.getRackId() != null) {
            map.put("rackId", flowingDo.getRackId() + "");
        }
        map.put("storageId", flowingDo.getStorageId() + "");
        if (!(req.getGoodQuantity() == 0 && req.getBadQuantity() == 0)) {
            req.setRackId(flowingDo.getRackId());
            req.setProductId(flowingDo.getProductId());
            req.setStorageId(flowingDo.getStorageId());

            Long addShopId = null;
            if (req.getGoodQuantity() > 0 || req.getBadQuantity() > 0) {
                addShopId = this.updateStockAdd(req, flowingDo.getId(), userId, null, false, flowingDo.getTips());
            }
            map.put("store", "0");//发货区还是配货区
            Long reduceShopId = null;
            if (req.getGoodQuantity() < 0 || req.getBadQuantity() < 0) {
                reduceShopId = this.updateStockReduce(req, map, flowingDo.getId(), userId, null, false, flowingDo.getTips());
            }
            if ((req.getGoodQuantity() > 0 || req.getBadQuantity() > 0) && (req.getGoodQuantity() < 0 || req.getBadQuantity() < 0)) {
                //当 又增 又减少 时 判断是不是同一个店铺
                if ((addShopId != null && reduceShopId != null) && addShopId.equals(reduceShopId)) {
                    flowingDo.setShopId(addShopId);
                }
            }
            else if (req.getGoodQuantity() > 0 || req.getBadQuantity() > 0) {
                flowingDo.setShopId(addShopId);
            }
            else if (req.getGoodQuantity() < 0 || req.getBadQuantity() < 0) {
                flowingDo.setShopId(reduceShopId);
            }
        }
        map.remove("store");
        map.put("notStore", "1");
        ProductStockDetailDto detailDto = dao.getStockByRackId(map);
        if (detailDto != null) {
            flowingDo.setLeftGoodQuantity(detailDto.getGoodQuantity());
            flowingDo.setLeftBadQuantity(detailDto.getBadQuantity());
            flowingDo.setLeftGoodLockingQuantity(detailDto.getGoodLockQuantity());
            flowingDo.setLeftBadLockingQuantity(detailDto.getBadLockQuantity());
        }
        productStockFlowingService.updateById(flowingDo);
    }


    /**
     * 申请库存盘点 盘盈盘亏
     *
     * @param req
     * @param userId
     */
    @Override
    public void applyUpdateStock(UpdateStockReq req, Long userId) {
        ProductInfoDo productInfoDo = productInfoDao.selectById(req.getProductId());
        if (req.getGoodQuantity() != 0) {
            productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.RackUpdate.getValue(), null, null, req.getProductId(), req.getStorageId(), req.getGoodQuantity(), 0, 0, req.getRackId(), "toCheck", productInfoDo.getCompanyId(), userId, StringUtils.isNotBlank(req.getTips()) ? req.getTips()+this.getNewTips(req.getStore()) : this.getTips(req.getStore()));
        }
        if (req.getBadQuantity() != 0) {
            productStockFlowingService.insertFlowing(StaticDict.Product_Flowing_Type.RackUpdate.getValue(), null, null, req.getProductId(), req.getStorageId(), 0, req.getBadQuantity(), 0, req.getRackId(), "toCheck", productInfoDo.getCompanyId(), userId, StringUtils.isNotBlank(req.getTips()) ? req.getTips()+this.getNewTips(req.getStore()) : this.getTips(req.getStore()));
        }

    }

    /**
     * 申请盘点 标记确认
     *
     * @param id
     * @param userId
     */
    @Override
    public void confirmApply(Long id, Long userId) {
        ProductStockFlowingDo flowingDo = productStockFlowingService.getById(id);
        if (flowingDo == null) {
            throw new BizException(SysConstant.No_Data);
        }
        if (!"toCheck".equals(flowingDo.getStatus())) {
            throw new BizException(SysConstant.Status_Error);
        }
        flowingDo.setStatus("checked");
        flowingDo.setUpdateTime(new Date());
        flowingDo.setUpdateBy(userId);
        productStockFlowingService.updateById(flowingDo);
    }


//    public void insertOldStockLog(int goodQuantity, int badQuantity, Long productId, Long storageId, Long userId, StockRecordDo recordDo, int store, Long flowingId) {
//        this.insertOldStockLog(goodQuantity, badQuantity, productId, storageId, recordDo.getShopId(), recordDo.getCanSellCount(), recordDo.getCanotSellCount(), userId, store, flowingId);
//
//    }

    public void insertOldStockLog(String orderNo , int goodQuantity, int badQuantity, Long productId, Long storageId, Long shopId, int afterCountGood, int afterCountBad, Long userId, int store, Long flowingId) {
        if (StringUtils.isBlank(orderNo)) {
            orderNo = this.getTips(store);
        }
//         orderNo = orderNo + this.getNewTips(store);
        ProductInfoDo productInfoDo = productInfoDao.selectById(productId);
        if (goodQuantity != 0) {
            stockLogService.saveAutoSendOutLog(0, productId, shopId, storageId,
                    goodQuantity, afterCountGood, productInfoDo.getCompanyId(), userId, orderNo, flowingId);
        }
        if (badQuantity != 0) {
            stockLogService.saveAutoSendOutLog(1, productId, shopId, storageId,
                    badQuantity, afterCountBad, productInfoDo.getCompanyId(), userId, orderNo, flowingId);
        }
    }

    public String getTips(int store) {
        String orderNo = "更新库存(";
        orderNo += (store == 0 ? "发货区" : (store == 1 ? "配货区" : "维修区")) + ")";
        return orderNo;
    }
    public String getNewTips(int store) {
        String orderNo = "(";
        orderNo += (store == 0 ? "发货区" : (store == 1 ? "配货区" : "维修区")) + ")";
        return orderNo;
    }



    public Map<String, Integer> dealWithOneRackStock(int goodQuantity, int badQuantity, ProductStockRackDo rackDo, String type, Long shopId, String tips, Long userId) {
        return this.dealWithOneRackStock(goodQuantity, badQuantity, rackDo, type, shopId, tips, userId, true);
    }

    @Override
    public Map<String, Integer> dealWithOneRackStock(int goodQuantity, int badQuantity, ProductStockRackDo rackDo, String type, Long shopId, String tips, Long userId, boolean flowingFlag) {
        int dGood = 0;
        int dBad = 0;
        if (rackDo.getGoodQuantity() > 0 || rackDo.getBadQuantity() > 0) {
            if (goodQuantity > 0) {
                if (goodQuantity > rackDo.getGoodQuantity()) {
                    dGood = rackDo.getGoodQuantity();
                    goodQuantity -= rackDo.getGoodQuantity();
                    rackDo.setGoodQuantity(0);
                } else {
                    dGood = goodQuantity;
                    rackDo.setGoodQuantity(rackDo.getGoodQuantity() - goodQuantity);
                    goodQuantity = 0;
                }
            }
            if (badQuantity > 0) {
                if (badQuantity > rackDo.getBadQuantity()) {
                    dBad = rackDo.getBadQuantity();
                    badQuantity -= rackDo.getBadQuantity();
                    rackDo.setBadQuantity(0);
                } else {
                    dBad = badQuantity;
                    rackDo.setBadQuantity(rackDo.getBadQuantity() - badQuantity);
                    badQuantity = 0;
                }
            }
            dao.updateById(rackDo);

            ProductStockDo stockDo = productStockDao.selectById(rackDo.getStockId());
            if (stockDo == null) {
                throw new BizException(SysConstant.StockRack_Stock_NotExist);
            }

            if ((dGood != 0 || dBad != 0) && flowingFlag) {
                //库存流水新
                productStockFlowingService.insertFlowing(type, shopId, stockDo.getProductId(), stockDo.getStorageId(), -dGood, -dBad, rackDo.getRackId(), stockDo.getCompanyId(), userId, tips);
            }

            if (rackDo.getGoodQuantity() == 0 && rackDo.getBadQuantity() == 0 && rackDo.getGoodLockQuantity() == 0 && rackDo.getBadLockQuantity() == 0) {
                dao.deleteById(rackDo);
            }
        }
        Map<String, Integer> result = new HashMap<>();
        result.put("dGood", dGood);
        result.put("dBad", dBad);
        result.put("goodQuantity", goodQuantity);
        result.put("badQuantity", badQuantity);

        return result;
    }

    @Override
    public Object getFlowing(Map<String, String> map) {
        IPage<StockFlowingDto> page = pageInitFlowingDto(map);
        IPage<StockFlowingDto> stockList = dao.getFlowingList(page, map);

        Map<Long, String> shopMap = new HashMap<>();
        for (StockFlowingDto record : stockList.getRecords()) {
            if (record.getShopId() == null && "done".equals(record.getStatus())) {
                List<StockLogDo> logDos = stockLogService.list(new LambdaQueryWrapper<StockLogDo>()
                        .eq(StockLogDo::getFlowingId, record.getId()).orderByAsc(StockLogDo::getShopId));
                List<StockFlowingShopDto> shop = new ArrayList<>();
                for (StockLogDo logDo : logDos) {
                    StockFlowingShopDto shopDto = new StockFlowingShopDto();
                    shopDto.setCount(logDo.getCount());
                    if (shopMap.get(logDo.getShopId()) == null) {
                        ShopDo shopDo = shopDao.selectById(logDo.getShopId());
                        if (shopDo == null) continue;
                        shopMap.put(shopDo.getId(), shopDo.getShopName());
                        shopDto.setShopName(shopDo.getShopName());
                    } else {
                        shopDto.setShopName(shopMap.get(logDo.getShopId()));
                    }
                    shopDto.setStatus(logDo.getStatus());
                    shop.add(shopDto);
                }
                record.setShop(shop);
//                record.setShopName("查看详情");
            } else if (record.getShopId() == null && !"done".equals(record.getStatus())) {
                record.setShopName("待分配");
            }
        }
        PageResult result = new PageResult(stockList.getRecords(), (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());
        return result;
    }


    /**
     * @param keyword
     * @param rackId
     * @param storageId
     * @param productId
     * @param companyId
     * @param notRack   null 则 按库位分,获取该商品 在指定库位上的库存
     * @return
     */
    @Override
    public List<ProductStockDto> getProductList(String keyword, Long rackId, Long storageId, Long productId, Long companyId, Integer notRack) {
//        LambdaQueryWrapper<ProductInfoDo> queryWrapper = new LambdaQueryWrapper<>();
//        if (StringUtils.isNotBlank(keyword)) {
//            queryWrapper.and(i -> i.like(ProductInfoDo::getCommoditySku, keyword).or().like(ProductInfoDo::getStorageSku, keyword));
//        }
//        if (companyId != null) {
//            queryWrapper.eq(ProductInfoDo::getCompanyId, companyId);
//        }
//        List<ProductInfoDo> list = productInfoDao.selectList(queryWrapper);

        Map<String, String> map = new HashMap<>();
        map.put("keyword", keyword);
        if (rackId != null) {
            map.put("rackId", rackId + "");
        }
//        else {
//            map.put("rackId", "0");
//        }
        if (storageId != null) {
            map.put("storageId", storageId + "");
        }
        if (companyId != null) {
            map.put("companyId", companyId + "");
        }
        if (productId != null) {
            map.put("productId", productId + "");
        }
        map.put("store", "0");
        if (notRack != null) {
            map.put("notRack", notRack + "");
        }
        List<ProductStockDto> list = dao.getProductList(map);
        return list;
    }

    @Override
    public PageResult getProductListPage(Map<String, String> map) {
        map.put("rackId", "0");
        map.put("store", "0");
        map.put("notRack", "1");
        IPage<ProductStockDto> page = pageInitDDDto(map);
        page = dao.getProductList(page, map);

        PageResult result = new PageResult(page.getRecords(), (int) page.getCurrent(), (int) page.getSize(), (int) page.getTotal(), (int) page.getPages());

        return result;
    }


    private IPage<ProductStockDto> pageInitDDDto(Map<String, String> map) {
        IPage<ProductStockDto> page = new Page();
        page.setSize(StringUtils.isNotBlank(map.get("pageSize")) ? Long.parseLong(map.get("pageSize")) : 10);
        page.setCurrent(StringUtils.isNotBlank(map.get("current")) ? Long.parseLong(map.get("current")) : 1);
        return page;
    }


}
